package org.evolAI.organism.code;

import java.util.EnumSet;
import java.util.List;
import java.util.Stack;

import org.apache.log4j.Logger;
import org.evolAI.organism.domain.Code;
import org.evolAI.organism.domain.Organism;
import org.evolAI.organism.domain.Step.Condition;

public class Executor {
	
	private final static Logger logger = Logger.getLogger(Executor.class);

	private final List<Code> codes;
    private final Organism org;
    private int stepCount;
	private boolean stop;
	private int maxDepth;
	private int maxSteps;

    //Evaluation Stacks
    private Stack<Integer> nums = new Stack<Integer>();
    private Stack<String> strings = new Stack<String>();
    private Stack<List<String>> lists = new Stack<List<String>>();
    private Stack<Condition> conds = new Stack<Condition>();

    public Executor(List<Code> codes, Organism org, int maxDepth, int maxSteps)
    {
        this.stepCount = 0;
        this.codes = codes;
        this.org = org;
        this.maxDepth = maxDepth;
        this.maxSteps = maxSteps;
    }
    
    public void execute(int codeNum, int depth) {
        if (codeNum < codes.size() && codeNum >= 0) {
            if (depth > maxDepth) {
                stop = true;
                return;
            }
                
            if (stop)
                return;

            CodeExecutor ce = new CodeExecutor(codes.get(codeNum), org, this, maxSteps);
            depth++;
            try
            {
                ce.execute(depth);
            }
            catch (OutOfMemoryError e)
            {
            	logger.error("Out of memory");
                stop = true;
                return;
            }
        }
    }
    
    public int getStepCount() {
		return stepCount;
	}

	public void setStepCount(int stepCount) {
		this.stepCount = stepCount;
	}

	public boolean isStop() {
		return stop;
	}

	public void setStop(boolean stop) {
		this.stop = stop;
	}

	public Stack<Integer> getNums() {
		return nums;
	}
	
	public Stack<String> getStrings() {
		return strings;
	}
	
	public Stack<List<String>> getLists() {
		return lists;
	}
	
	public Stack<Condition> getConds() {
		return conds;
	}
}
